﻿using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics.Contracts;
using IronPython.Hosting;
using Microsoft.Scripting;
using Microsoft.Scripting.Hosting;
using Wombat.Core.Services;

namespace Wombat.Scripting
{
    public class PythonCodeServicePeer: IDynamicCodeServicePeer
    {
        private ScriptSource _scriptSource;
        private ScriptScope _scriptScope;
        private string _code;
        private SourceCodeKind _sourceCodeKind;
        private ScriptEngine _scriptEngine;

        public void SetExpression(string expression)
        {
            SetCode(expression, SourceCodeKind.Expression);
        }

        public void SetCode(string code)
        {
            SetCode(code, SourceCodeKind.Statements);
        }

        private void SetCode(string code, SourceCodeKind kind)
        {
            _code = code;
            _sourceCodeKind = kind;
        }

        public dynamic Execute(IDictionary<string, object> inputParameters)
        {
            Contract.Assert(!string.IsNullOrEmpty(_code));

            if (_scriptEngine == null || _scriptSource == null)
            {
                _scriptEngine = Python.CreateEngine();
                _scriptSource = _scriptEngine.CreateScriptSourceFromString(_code, _sourceCodeKind);
            }
            
            _scriptScope = _scriptEngine.CreateScope();
            foreach (var variable in inputParameters.Keys)
            {
                _scriptScope.SetVariable(variable, inputParameters[variable]);
            }
            return _scriptSource.Execute(_scriptScope);
        }

        public bool TryGetVariable(string variableName, out object returnVal)
        {
            Contract.Assert(!string.IsNullOrEmpty(variableName));
            Contract.Assert(_scriptSource != null);

            return _scriptScope.TryGetVariable(variableName, out returnVal);
        }
    }
}
